﻿// -----------------------------------------------------------------------
// <copyright file="IntVector.cs" company="The BomberJoe Team">
// Author: Emil D. Buhl <ebuh@itu.dk>
// </copyright>
// -----------------------------------------------------------------------

namespace Bomberman
{
    using System.Diagnostics.Contracts;

    /// <summary>
    /// A two dimensional vector, implemented using integers.
    /// </summary>
    public struct IntVector
    {
        private readonly int _x;

        private readonly int _y;

        /// <summary>
        /// Initializes a new instance of the IntVector struct.
        /// </summary>
        /// <param name="x">The X value of the vector.</param>
        /// <param name="y">The Y value of the vector.</param>
        public IntVector(int x, int y)
        {
            _x = x;
            _y = y;
        }

        /// <summary>
        /// Gets the X value of the vector.
        /// </summary>
        /// <value>
        /// The x value.
        /// </value>
        public int X 
        {
            get
            {
                return _x;
            } 
        }

        /// <summary>
        /// Gets the Y value of the vector.
        /// </summary>
        /// <value>
        /// The y value.
        /// </value>
        public int Y
        {
            get
            {
                return _y;
            }
        }

        /// <summary>
        /// Adds a vector to another.
        /// </summary>
        /// <param name="vector1">The first vector.</param>
        /// <param name="vector2">The second vector.</param>
        /// <returns>The sum of the two vector.</returns>
        public static IntVector operator +(IntVector vector1, IntVector vector2)
        {
            return new IntVector(vector1.X + vector2.X, vector1.Y + vector2.Y);
        }

        /// <summary>
        /// Substract a vector from this vector.
        /// </summary>
        /// <param name="vector1">The minuend.</param>
        /// <param name="vector2">The subtrahend.</param>
        /// <returns>The difference.</returns>
        public static IntVector operator -(IntVector vector1, IntVector vector2)
        {
            return new IntVector(vector1.X - vector2.X, vector1.Y - vector2.Y); 
        }

        /// <summary>
        /// Multiplies a vectors value with a certain factor.
        /// </summary>
        /// <param name="vector">The vector to be multiplied.</param>
        /// <param name="scale">The factor.</param>
        /// <returns>A new vector which values equals the old vector values multiplied with the scale.</returns>
        public static IntVector operator *(IntVector vector, int scale)
        {
            return new IntVector(vector.X * scale, vector.Y * scale);
        }

        /// <summary>
        /// Multiplies a vectors value with a certain factor.
        /// </summary>
        /// <param name="scale">The factor.</param>
        /// <param name="vector">The vector to be multiplied.</param>
        /// <returns>A new vector which values equals the old vector values multiplied with the scale.</returns>
        public static IntVector operator *(int scale, IntVector vector)
        {
            return vector * scale;
        }

        /// <summary>
        /// Compares and checks if two vectors are equal to eachother.
        /// </summary>
        /// <param name="vector1">The first vector to be compared.</param>
        /// <param name="vector2">The second vector to be compared.</param>
        /// <returns>Whether vector1 is equal vector2.</returns>
        public static bool operator ==(IntVector vector1, IntVector vector2)
        {
            return vector1.X == vector2.X & vector1.Y == vector2.Y;
        }

        /// <summary>
        /// Compares and checks if two vectors are not equal to eachother.
        /// </summary>
        /// <param name="vector1">The first vector to be compared.</param>
        /// <param name="vector2">The second vector to be compared.</param>
        /// <returns>Whether vector1 is not equal vector2.</returns>
        public static bool operator !=(IntVector vector1, IntVector vector2)
        {
            return !(vector1 == vector2);
        }

        /// <summary>
        /// Check and compares whether this vector is equal an object
        /// </summary>
        /// <param name="obj">object to be compared</param>
        /// <returns>A value indicating the equality</returns>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            return (obj is IntVector) && (this == (IntVector)obj);
        }

        /// <summary>
        /// Calculates a hashCode for the vector
        /// </summary>
        /// <returns>A hashCode representation of the vector</returns>
        public override int GetHashCode()
        {
            unchecked
            {
                return (this._x * 397) ^ this._y;
            }
        }
    }
}
